from __future__ import absolute_import, division, print_function, unicode_literals

import datetime  # For datetime objects
import os.path  # To manage paths
import sys  # To find out the script name (in argv[0])

# Import the backtrader platform
import backtrader as bt

import MySQLDataFeed as mdf
import SimpleMySqlClass as smc
import talib as talib
import numpy as np


class DoubleAverages(bt.Strategy):
    params = (("period_sma20", 20), ("period_sma60", 60))

    # 打印日志
    def log(self, txt, dt=None):
        dt = dt or self.data.datetime.date(0)
        print("%s, %s" % (dt, txt))

    def __init__(self):
        # 用于保存订单
        self.order = None
        # 订单价格
        self.buyprice = None
        # 订单佣金
        self.buycomm = None

        # 定义变量保存所有收盘价
        self.dataopen = self.data.open
        self.datahigh = self.data.high
        self.datalow = self.data.low
        self.dataclose = self.data.close
        self.datavolume = self.data.volume

        self.sma20 = bt.talib.WMA(self.dataclose, timeperiod=self.params.period_sma20)
        # # 计算60日均线
        self.sma60 = bt.talib.WMA(self.dataclose, timeperiod=self.params.period_sma60)
        bt.indicators.MACDHisto(self.datas[0])
        bt.talib.MACD(self.dataclose)
        # rsi = bt.indicators.RSI(self.datas[0])
        #real = bt.talib.MINUS_DM(self.datahigh, self.datalow)
        real = bt.talib.RSI(self.dataclose, timeperiod=14)
        real = bt.talib.MFI(
            self.datahigh, self.datalow, self.dataclose, self.datavolume
        )
        real = bt.talib.CCI(self.datahigh, self.datalow, self.dataclose)

        # Indicators for the plotting show
        # bt.indicators.ExponentialMovingAverage(self.datas[0], period=25)
        # bt.indicators.WeightedMovingAverage(self.datas[0], period=25, subplot=True)
        # bt.indicators.StochasticSlow(self.datas[0])
        #

        #
        # bt.indicators.SmoothedMovingAverage(rsi, period=10)
        # bt.indicators.ATR(self.datas[0], plot=False)
        # bt.talib.HT_DCPERIOD(self.dataclose)
        # bt.talib.HT_DCPHASE(self.dataclose)
        # bt.talib.HT_TRENDMODE(self.dataclose)
        # real = bt.talib.ADX(self.datahigh, self.datalow, self.dataclose)
        # real = bt.talib.ADXR(self.datahigh, self.datalow, self.dataclose)
        # aroondown, aroonup = bt.talib.AROON(self.datahigh, self.datalow)
        # 顺势指标
        # real = bt.talib.CCI(self.datahigh, self.datalow, self.dataclose)

        # real = bt.talib.CMO(self.dataclose)

        # 资金流量指标
        # real = bt.talib.MFI(
        #     self.datahigh, self.datalow, self.dataclose, self.datavolume
        # )

        # real = bt.talib.MINUS_DM(self.datahigh, self.datalow)

        # 上升动向值
        # real = bt.talib.MOM(self.dataclose, timeperiod=10)

        # 相对强弱指数
        # real = bt.talib.RSI(self.dataclose, timeperiod=14)

        # real = bt.talib.WILLR(
        #     self.datahigh, self.datalow, self.dataclose, timeperiod=14
        # )

        self.star = dict()
        self.crows = dict()
        self.twocrows = dict()
        self.c3insides = dict()
        # 定义全局变量
        self.count = 0
        for data in self.datas:
            print("data._id = ", data._id)
            # 转为tabib要求的数据格式
            opens = np.array(data.open.array)
            highs = np.array(data.high.array)
            lows = np.array(data.low.array)
            closes = np.array(data.close.array)
            volumes = np.array(data.volume.array)
            # print(opens)
            # 数据放入self中

            ############ ------上涨---------
            # 名称： Three Inside Up/Down 三内部上涨和下跌
            # 简介：三日K线模式，母子信号+长K线，以三内部上涨为例，K线为阴阳阳， 第三天收盘价高于第一天开盘价，第二天K线在第一天K线内部，预示着股价上涨。
            integer = talib.CDL3INSIDE(opens, highs, lows, closes)
            print(integer)
            # 名称：Three Outside Up/Down 三外部上涨和下跌
            # 简介：三日K线模式，与三内部上涨和下跌类似，K线为阴阳阳，但第一日与第二日的K线形态相反， 以三外部上涨为例，第一日K线在第二日K线内部，预示着股价上涨。
            integer = talib.CDL3OUTSIDE(opens, highs, lows, closes)
            print(integer)
            # 名称：Abandoned Baby 弃婴
            # 简介：三日K线模式，第二日价格跳空且收十字星（开盘价与收盘价接近， 最高价最低价相差不大），预示趋势反转，发生在顶部下跌，底部上涨。
            integer = talib.CDLABANDONEDBABY(opens, highs, lows, closes, penetration=0)
            print(integer)
            # 名称：Belt-hold 捉腰带线
            # 简介：两日K线模式，下跌趋势中，第一日阴线， 第二日开盘价为最低价，阳线，收盘价接近最高价，预示价格上涨。
            integer = talib.CDLBELTHOLD(opens, highs, lows, closes)
            print(integer)
            # 名称：Breakaway 脱离
            # 简介：五日K线模式，以看涨脱离为例，下跌趋势中，第一日长阴线，第二日跳空阴线，延续趋势开始震荡， 第五日长阳线，收盘价在第一天收盘价与第二天开盘价之间，预示价格上涨。
            integer = talib.CDLBREAKAWAY(opens, highs, lows, closes)
            print(integer)
            # 名称：Upside/Downside Gap Three Methods 上升/下降跳空三法
            # 简介：五日K线模式，以上升跳空三法为例，上涨趋势中，第一日长阳线，第二日短阳线，第三日跳空阳线，第四日阴线，开盘价与收盘价于前两日实体内， 第五日长阳线，收盘价高于第一日收盘价，预示股价上升。
            integer = talib.CDLXSIDEGAP3METHODS(opens, highs, lows, closes)
            print(integer)
            # 名称：Three Advancing White Soldiers 三个白兵
            # 简介：三日K线模式，三日K线皆阳， 每日收盘价变高且接近最高价，开盘价在前一日实体上半部，预示股价上升。
            integer = talib.CDL3WHITESOLDIERS(opens, highs, lows, closes)
            print(integer)
            # 名称：Three Stars In The South 南方三星
            # 简介：三日K线模式，与大敌当前相反，三日K线皆阴，第一日有长下影线， 第二日与第一日类似，K线整体小于第一日，第三日无下影线实体信号， 成交价格都在第一日振幅之内，预示下跌趋势反转，股价上升。
            integer = talib.CDL3STARSINSOUTH(opens, highs, lows, closes)
            print(integer)
            # 名称：Harami Pattern 母子线
            # 简介：二日K线模式，分多头母子与空头母子，两者相反，以多头母子为例，在下跌趋势中，第一日K线长阴， 第二日开盘价收盘价在第一日价格振幅之内，为阳线，预示趋势反转，股价上升。
            integer = talib.CDLHARAMI(opens, highs, lows, closes)
            print(integer)
            # 函数名：CDLRISEFALL3METHODS
            # 名称：Rising/Falling Three Methods 上升/下降三法
            # 简介： 五日K线模式，以上升三法为例，上涨趋势中， 第一日长阳线，中间三日价格在第一日范围内小幅震荡， 第五日长阳线，收盘价高于第一日收盘价，预示股价上升。
            integer = talib.CDLRISEFALL3METHODS(opens, highs, lows, closes)
            print(integer)
            # 名称：Tasuki Gap 跳空并列阴阳线
            # 简介：三日K线模式，分上涨和下跌，以上升为例， 前两日阳线，第二日跳空，第三日阴线，收盘价于缺口中，上升趋势持续。
            integer = talib.CDLTASUKIGAP(opens, highs, lows, closes)
            print(integer)

            #############-----延续-----

            # 名称：Mat Hold 铺垫
            # 简介：五日K线模式，上涨趋势中，第一日阳线，第二日跳空高开影线， 第三、四日短实体影线，第五日阳线，收盘价高于前四日，预示趋势持续。
            integer = talib.CDLMATHOLD(opens, highs, lows, closes, penetration=0)
            print(integer)
            # 名称：Closing Marubozu 收盘缺影线
            # 简介：一日K线模式，以阳线为例，最低价低于开盘价，收盘价等于最高价， 预示着趋势持续。
            integer = talib.CDLCLOSINGMARUBOZU(opens, highs, lows, closes)
            print(integer)
            # 名称：Up/Down-gap side-by-side white lines 向上/下跳空并列阳线
            # 简介：二日K线模式，上升趋势向上跳空，下跌趋势向下跳空, 第一日与第二日有相同开盘价，实体长度差不多，则趋势持续。
            integer = talib.CDLGAPSIDESIDEWHITE(opens, highs, lows, closes)
            print(integer)
            # 名称：Thrusting Pattern 插入
            # 简介：二日K线模式，与颈上线类似，下跌趋势中，第一日长阴线，第二日开盘价跳空， 收盘价略低于前一日实体中部，与颈上线相比实体较长，预示着趋势持续。
            integer = talib.CDLTHRUSTING(opens, highs, lows, closes)
            print(integer)
            # 名称：Separating Lines 分离线
            # 简介：二日K线模式，上涨趋势中，第一日阴线，第二日阳线， 第二日开盘价与第一日相同且为最低价，预示着趋势继续。
            integer = talib.CDLSEPARATINGLINES(opens, highs, lows, closes)
            print(integer)
            # 名称：Hikkake Pattern 陷阱
            # 简介：三日K线模式，与母子类似，第二日价格在前一日实体范围内, 第三日收盘价高于前两日，反转失败，趋势继续。
            integer = talib.CDLHIKKAKE(opens, highs, lows, closes)
            print(integer)
            # 名称：Modified Hikkake Pattern 修正陷阱
            # 简介：三日K线模式，与陷阱类似，上升趋势中，第三日跳空高开； 下跌趋势中，第三日跳空低开，反转失败，趋势继续。
            integer = talib.CDLHIKKAKEMOD(opens, highs, lows, closes)
            print(integer)
            ############------底部反转------

            # 名称： Concealing Baby Swallow 藏婴吞没
            # 简介：四日K线模式，下跌趋势中，前两日阴线无影线 ，第二日开盘、收盘价皆低于第二日，第三日倒锤头， 第四日开盘价高于前一日最高价，收盘价低于前一日最低价，预示着底部反转。
            integer = talib.CDLCONCEALBABYSWALL(opens, highs, lows, closes)
            print(integer)
            # 名称：Gravestone Doji 墓碑十字/倒T十字
            # 简介：一日K线模式，开盘价与收盘价相同，上影线长，无下影线，预示底部反转。
            integer = talib.CDLGRAVESTONEDOJI(opens, highs, lows, closes)
            print(integer)
            # 名称：Hammer 锤头
            # 简介：一日K线模式，实体较短，无上影线， 下影线大于实体长度两倍，处于下跌趋势底部，预示反转。
            integer = talib.CDLHAMMER(opens, highs, lows, closes)
            print(integer)
            # 名称：Inverted Hammer 倒锤头
            # 简介：一日K线模式，上影线较长，长度为实体2倍以上， 无下影线，在下跌趋势底部，预示着趋势反转。
            integer = talib.CDLINVERTEDHAMMER(opens, highs, lows, closes)
            print(integer)
            # 名称：Ladder Bottom 梯底
            # 简介：五日K线模式，下跌趋势中，前三日阴线， 开盘价与收盘价皆低于前一日开盘、收盘价，第四日倒锤头，第五日开盘价高于前一日开盘价， 阳线，收盘价高于前几日价格振幅，预示着底部反转。
            integer = talib.CDLLADDERBOTTOM(opens, highs, lows, closes)
            print(integer)
            # 名称：Morning Doji Star 十字晨星
            # 简介：三日K线模式， 基本模式为晨星，第二日K线为十字星，预示底部反转。
            integer = talib.CDLMORNINGDOJISTAR(
                opens, highs, lows, closes, penetration=0
            )
            print(integer)
            # 名称：Morning Star 晨星
            # 简介：三日K线模式，下跌趋势，第一日阴线， 第二日价格振幅较小，第三天阳线，预示底部反转。
            integer = talib.CDLMORNINGSTAR(opens, highs, lows, closes, penetration=0)
            print(integer)
            # 名称：Matching Low 相同低价
            # 简介：二日K线模式，下跌趋势中，第一日长阴线， 第二日阴线，收盘价与前一日相同，预示底部确认，该价格为支撑位。
            integer = talib.CDLMATCHINGLOW(opens, highs, lows, closes)
            print(integer)
            # 名称：Piercing Pattern 刺透形态
            # 简介：两日K线模式，下跌趋势中，第一日阴线，第二日收盘价低于前一日最低价， 收盘价处在第一日实体上部，预示着底部反转。
            integer = talib.CDLPIERCING(opens, highs, lows, closes)
            #############-----顶部反转----------
            # 简介：三日K线模式，基本模式为暮星，第二日收盘价和开盘价相同，预示顶部反转。
            integer = talib.CDLEVENINGDOJISTAR(
                opens, highs, lows, closes, penetration=0
            )
            print(integer)
            # 名称：Evening Star 暮星
            # 简介：三日K线模式，与晨星相反，上升趋势中, 第一日阳线，第二日价格振幅较小，第三日阴线，预示顶部反转。
            integer = talib.CDLEVENINGSTAR(opens, highs, lows, closes, penetration=0)
            print(integer)
            #############-------反转----------

            # 名称：Doji Star 十字星
            # 简介：一日K线模式，开盘价与收盘价基本相同，上下影线不会很长，预示着当前趋势反转。
            integer = talib.CDLDOJISTAR(opens, highs, lows, closes)
            print(integer)
            # 名称：Dragonfly Doji 蜻蜓十字/T形十字
            # 简介：一日K线模式，开盘后价格一路走低， 之后收复，收盘价与开盘价相同，预示趋势反转。
            integer = talib.CDLDRAGONFLYDOJI(opens, highs, lows, closes)
            print(integer)
            # 名称：Engulfing Pattern 吞噬模式
            # 简介：两日K线模式，分多头吞噬和空头吞噬，以多头吞噬为例，第一日为阴线， 第二日阳线，第一日的开盘价和收盘价在第二日开盘价收盘价之内，但不能完全相同。
            integer = talib.CDLENGULFING(opens, highs, lows, closes)
            print(integer)

            # 名称：Hanging Man 上吊线
            # 简介：一日K线模式，形状与锤子类似，处于上升趋势的顶部，预示着趋势反转。
            integer = talib.CDLHANGINGMAN(opens, highs, lows, closes)
            print(integer)
            # 名称：Harami Cross Pattern 十字孕线
            # 简介：二日K线模式，与母子县类似，若第二日K线是十字线， 便称为十字孕线，预示着趋势反转。
            integer = talib.CDLHARAMICROSS(opens, highs, lows, closes)
            print(integer)
            # 名称：High-Wave Candle 风高浪大线
            # 简介：三日K线模式，具有极长的上/下影线与短的实体，预示着趋势反转。
            integer = talib.CDLHIGHWAVE(opens, highs, lows, closes)
            print(integer)
            # 名称：Homing Pigeon 家鸽
            # 简介：二日K线模式，与母子线类似，不同的的是二日K线颜色相同， 第二日最高价、最低价都在第一日实体之内，预示着趋势反转。
            integer = talib.CDLHOMINGPIGEON(opens, highs, lows, closes)
            print(integer)
            # 名称：Marubozu 光头光脚/缺影线
            # 简介：一日K线模式，上下两头都没有影线的实体， 阴线预示着熊市持续或者牛市反转，阳线相反。
            integer = talib.CDLMARUBOZU(opens, highs, lows, closes)
            print(integer)
            # 名称：Tristar Pattern 三星
            # 简介：三日K线模式，由三个十字组成， 第二日十字必须高于或者低于第一日和第三日，预示着反转。
            integer = talib.CDLTRISTAR(opens, highs, lows, closes)
            print(integer)
            # 名称：Unique 3 River 奇特三河床
            # 简介：三日K线模式，下跌趋势中，第一日长阴线，第二日为锤头，最低价创新低，第三日开盘价低于第二日收盘价，收阳线， 收盘价不高于第二日收盘价，预示着反转，第二日下影线越长可能性越大。
            integer = talib.CDLUNIQUE3RIVER(opens, highs, lows, closes)
            print(integer)
            #############------下跌--------

            # 名称：Two Crows 两只乌鸦
            # 简介：三日K线模式，第一天长阳，第二天高开收阴，第三天再次高开继续收阴， 收盘比前一日收盘价低，预示股价下跌。
            integer = talib.CDL2CROWS(opens, highs, lows, closes)
            print(integer)
            # 名称：Three Black Crows 三只乌鸦
            # 简介：三日K线模式，连续三根阴线，每日收盘价都下跌且接近最低价， 每日开盘价都在上根K线实体内，预示股价下跌。
            integer = talib.CDL3BLACKCROWS(opens, highs, lows, closes)
            print(integer)
            # 名称： Three-Line Strike 三线打击
            # 简介：四日K线模式，前三根阳线，每日收盘价都比前一日高， 开盘价在前一日实体内，第四日市场高开，收盘价低于第一日开盘价，预示股价下跌。
            integer = talib.CDL3LINESTRIKE(opens, highs, lows, closes)
            print(integer)
            # 名称：Advance Block 大敌当前
            # 简介：三日K线模式，三日都收阳，每日收盘价都比前一日高， 开盘价都在前一日实体以内，实体变短，上影线变长。
            integer = talib.CDLADVANCEBLOCK(opens, highs, lows, closes)
            print(integer)
            # 名称：Counterattack 反击线
            # 简介：二日K线模式，与分离线类似。
            integer = talib.CDLCOUNTERATTACK(opens, highs, lows, closes)
            print(integer)
            # 名称：Dark Cloud Cover 乌云压顶
            # 简介：二日K线模式，第一日长阳，第二日开盘价高于前一日最高价， 收盘价处于前一日实体中部以下，预示着股价下跌。
            integer = talib.CDLDARKCLOUDCOVER(opens, highs, lows, closes, penetration=0)
            print(integer)
            # 名称：Identical Three Crows 三胞胎乌鸦
            # 简介：三日K线模式，上涨趋势中，三日都为阴线，长度大致相等， 每日开盘价等于前一日收盘价，收盘价接近当日最低价，预示价格下跌。
            integer = talib.CDLIDENTICAL3CROWS(opens, highs, lows, closes)
            print(integer)
            # 名称：In-Neck Pattern 颈内线
            # 简介：二日K线模式，下跌趋势中，第一日长阴线， 第二日开盘价较低，收盘价略高于第一日收盘价，阳线，实体较短，预示着下跌继续。
            integer = talib.CDLINNECK(opens, highs, lows, closes)
            print(integer)
            # 名称：Doji 十字
            # 简介：一日K线模式，开盘价与收盘价基本相同。
            integer = talib.CDLDOJI(opens, highs, lows, closes)
            print(integer)
            # 名称：Kicking 反冲形态
            # 简介：二日K线模式，与分离线类似，两日K线为秃线，颜色相反，存在跳空缺口。
            integer = talib.CDLKICKING(opens, highs, lows, closes)
            print(integer)
            # 名称：Kicking - bull/bear determined by the longer marubozu 由较长缺影线决定的反冲形态
            # 简介：二日K线模式，与反冲形态类似，较长缺影线决定价格的涨跌。
            integer = talib.CDLKICKINGBYLENGTH(opens, highs, lows, closes)
            print(integer)
            # 名称：Long Legged Doji 长脚十字
            # 简介：一日K线模式，开盘价与收盘价相同居当日价格中部，上下影线长， 表达市场不确定性。
            integer = talib.CDLLONGLEGGEDDOJI(opens, highs, lows, closes)
            print(integer)
            # 名称：Long Line Candle 长蜡烛
            # 简介：一日K线模式，K线实体长，无上下影线。
            integer = talib.CDLLONGLINE(opens, highs, lows, closes)
            print(integer)
            # 名称：On-Neck Pattern 颈上线
            # 简介：二日K线模式，下跌趋势中，第一日长阴线，第二日开盘价较低， 收盘价与前一日最低价相同，阳线，实体较短，预示着延续下跌趋势。
            integer = talib.CDLONNECK(opens, highs, lows, closes)
            print(integer)
            # 名称：Rickshaw Man 黄包车夫
            # 简介：一日K线模式，与长腿十字线类似， 若实体正好处于价格振幅中点，称为黄包车夫。
            integer = talib.CDLRICKSHAWMAN(opens, highs, lows, closes)
            print(integer)
            # 名称：Shooting Star 射击之星
            # 简介：一日K线模式，上影线至少为实体长度两倍， 没有下影线，预示着股价下跌
            integer = talib.CDLSHOOTINGSTAR(opens, highs, lows, closes)
            print(integer)
            # 名称：Short Line Candle 短蜡烛
            # 简介：一日K线模式，实体短，无上下影线
            integer = talib.CDLSHORTLINE(opens, highs, lows, closes)
            print(integer)
            # 名称：Spinning Top 纺锤
            # 简介：一日K线，实体小。
            integer = talib.CDLSPINNINGTOP(opens, highs, lows, closes)
            print(integer)
            # 名称：Stalled Pattern 停顿形态
            # 简介：三日K线模式，上涨趋势中，第二日长阳线， 第三日开盘于前一日收盘价附近，短阳线，预示着上涨结束
            integer = talib.CDLSTALLEDPATTERN(opens, highs, lows, closes)
            print(integer)
            # 名称：Stick Sandwich 条形三明治
            # 简介：三日K线模式，第一日长阴线，第二日阳线，开盘价高于前一日收盘价， 第三日开盘价高于前两日最高价，收盘价于第一日收盘价相同。
            integer = talib.CDLSTICKSANDWICH(opens, highs, lows, closes)
            print(integer)
            # 名称：Takuri (Dragonfly Doji with very long lower shadow) 探水竿
            # 简介：一日K线模式，大致与蜻蜓十字相同，下影线长度长。
            integer = talib.CDLTAKURI(opens, highs, lows, closes)
            print(integer)
            # 名称：Upside Gap Two Crows 向上跳空的两只乌鸦
            # 简介：三日K线模式，第一日阳线，第二日跳空以高于第一日最高价开盘， 收阴线，第三日开盘价高于第二日，收阴线，与第一日比仍有缺口。
            integer = talib.CDLUPSIDEGAP2CROWS(opens, highs, lows, closes)
            print(integer)

            # 简介：真实波动幅度均值（ATR)是 以 N 天的指数移动平均数平均後的交易波动幅度。 计算公式：一天的交易幅度只是单纯地 最大值 - 最小值。
            # 而真实波动幅度则包含昨天的收盘价，若其在今天的幅度之外：
            # 真实波动幅度 = max(最大值,昨日收盘价) − min(最小值,昨日收盘价) 真实波动幅度均值便是「真实波动幅度」的 N 日 指数移动平均数。
            real = talib.ATR(highs, lows, closes, timeperiod=14)
            print("atr 波动率=", real)

            # 名称：Chaikin A/D Line 累积/派发线（Accumulation/Distribution Line）
            # 简介：Marc Chaikin提出的一种平衡交易量指标，以当日的收盘价位来估算成交流量，用于估定一段时间内该证券累积的资金流量。
            # 计算公式： 多空对比 = [（收盘价- 最低价） - （最高价 - 收盘价）] / （最高价 - 最低价)
            # 若最高价等于最低价： 多空对比 = （收盘价 / 昨收盘） - 1
            # 研判：
            # 1、A/D测量资金流向，向上的A/D表明买方占优势，而向下的A/D表明卖方占优势
            # 2、A/D与价格的背离可视为买卖信号，即底背离考虑买入，顶背离考虑卖出
            # 3、应当注意A/D忽略了缺口的影响，事实上，跳空缺口的意义是不能轻易忽略的
            real = talib.AD(highs, lows, closes, volumes)
            print("a/d 积累/派发线 =", real)

            # 名称：Chaikin A/D Oscillator Chaikin震荡指标
            # 简介：将资金流动情况与价格行为相对比，检测市场中资金流入和流出的情况
            # 计算公式：fastperiod A/D - slowperiod A/D
            # 研判：
            # 1、交易信号是背离：看涨背离做多，看跌背离做空
            # 2、股价与90天移动平均结合，与其他指标结合
            # 3、由正变负卖出，由负变正买进
            real = talib.ADOSC(
                highs, lows, closes, volumes, fastperiod=3, slowperiod=10
            )
            print("资金流动情况与价格行为相对比 =", real)

            # 名称：On Balance Volume 能量潮
            # 简介：Joe Granville提出，通过统计成交量变动的趋势推测股价趋势
            # 计算公式：以某日为基期，逐日累计每日上市股票总成交量，若隔日指数或股票上涨 ，则基期OBV加上本日成交量为本日OBV。隔日指数或股票下跌， 则基期OBV减去本日成交量为本日OBV
            # 研判：
            # 1、以“N”字型为波动单位，一浪高于一浪称“上升潮”，下跌称“跌潮”；上升潮买进，跌潮卖出
            # 2、须配合K线图走势
            # 3、用多空比率净额法进行修正，但不知TA-Lib采用哪种方法
            # 计算公式： 多空比率净额= [（收盘价－最低价）－（最高价-收盘价）] ÷（ 最高价－最低价）×成交量
            real = talib.OBV(closes, volumes)
            print("obv能量潮 =", real)

    def notify_order(self, order):
        # 等待订单提交、订单被cerebro接受
        if order.status in [order.Submitted, order.Accepted]:
            return

        # 等待订单完成
        if order.status in [order.Completed]:
            if order.isbuy():
                self.log(
                    "买 EXECUTED, 开仓价格: %.2f, 花费: %.2f, Comm %.2f"
                    % (order.executed.price, order.executed.value, order.executed.comm)
                )

            else:
                self.log(
                    "卖 EXECUTED, 卖出价格: %.2f, 收回资金: %.2f, Comm %.2f"
                    % (order.executed.price, order.executed.value, order.executed.comm)
                )

        # 如果订单保证金不足，将不会完成，而是执行以下拒绝程序
        elif order.status in [order.Canceled, order.Margin, order.Rejected]:
            self.log("拒绝执行，Order Canceled/Margin/Rejected")

        self.order = None

    def notify_trade(self, trade):
        if not trade.isclosed:
            return

        self.log(
            "开始交易 PROFIT, GROSS %.2f, NET %.2f" % (trade.pnl, trade.pnlcomm)
        )  # pnl：盈利  pnlcomm：手续费

    # 策略逻辑实现
    def next(self):
        

        # 当今天的20日均线大于60日均线并且昨天的20日均线小于60日均线，则进入市场（买）
        if self.sma20[0] > self.sma60[0] and self.sma20[-1] < self.sma60[-1]:
            # 判断订单是否完成，完成则为None，否则为订单信息
            if self.order:
                return

            # 若上一个订单处理完成，可继续执行买入操作
            self.order = self.buy()

        # 当今天的20日均线小于60日均线并且昨天的20日均线大于60日均线，则退出市场（卖）
        elif self.sma20[0] < self.sma60[0] and self.sma20[-1] > self.sma60[-1]:
            # 卖出
            self.order = self.sell()

        for data in self.datas:
            pos = self.getposition(data).size
            # 函数出现100就代表出现十字星形态，做买入
            # if self.star[data._id][self.count] == -100:
            #     print("十字星了 position=", str(pos))

        # 自增处理
        self.count = self.count + 1


if __name__ == "__main__":
    # Create a cerebro entity
    cerebro = bt.Cerebro()

    # Add a strategy
    cerebro.addstrategy(DoubleAverages)

    tableName = "t_stock_k_data"
    sql = f"select sd_date, sd_open, sd_high, sd_low, sd_close, sd_volume from {tableName}"
    # sql = f"select sd_date as date, sd_code as code, sd_open as code, sd_high as high, sd_low as low, sd_close as low, sd_volume as volume, sd_amount as amount from {tableName}"

    data = mdf.MySQLDataFeed(sql)

    # Add the Data Feed to Cerebro
    cerebro.adddata(data, name="2Line")

    # Set our desired cash start
    cerebro.broker.setcash(1000.0)

    # Add a FixedSize sizer according to the stake
    cerebro.addsizer(bt.sizers.FixedSize, stake=10)

    # Set the commission
    cerebro.broker.setcommission(commission=0.0005)

    # Print out the starting conditions
    print("Starting Portfolio Value: %.2f" % cerebro.broker.getvalue())

    # Run over everything
    cerebro.run()

    # Print out the final result
    print("Final Portfolio Value: %.2f" % cerebro.broker.getvalue())

    # Plot the result
    cerebro.plot(style="candle", barup="red", bardown="green")
